package com.lzy.cloud.payment.component.pay;

import com.lzy.cloud.payment.constants.CommonConstants;
import com.lzy.cloud.payment.dtos.pay.*;
import com.lzy.cloud.payment.dtos.payment.PayBillDto;
import com.lzy.cloud.payment.dtos.payment.PayInfoDto;
import com.lzy.cloud.payment.dtos.payment.PayRefundInfoDto;
import com.lzy.cloud.payment.entity.PayRefundInfo;
import com.lzy.cloud.payment.pay.alipay.AlipayCore;
import com.lzy.cloud.payment.pay.weixin.Config;
import com.lzy.cloud.payment.pay.weixin.WxPayApi;
import com.lzy.cloud.payment.pay.weixin.WxPayData;
import com.lzy.cloud.payment.pay.weixin.WxService;
import com.lzy.cloud.payment.remote.RabbitmqApi;
import com.lzy.cloud.payment.service.PayBillService;
import com.lzy.cloud.payment.service.PayInfoService;
import com.lzy.cloud.payment.service.PayRefundInfoService;
import com.lzy.cloud.payment.utils.Common;
import com.lzy.cloud.payment.utils.StringUtil;
import com.lzy.framework.core.ensure.Ensure;
import com.lzy.framework.core.utils.DateUtil;
import com.lzy.framework.core.utils.DozerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

@Component("weixin/pay/commons")
public class WeixinPayCommons extends PayCommons<WeixinPayDTO> {

    private static final Logger logger = LoggerFactory.getLogger(WeixinPayCommons.class);

    @Autowired
    private PayRefundInfoService payRefundInfoService;

    @Autowired
    private PayBillService payBillService;

    @Autowired
    private PayInfoService payInfoService;

    @Autowired
    private RabbitmqApi rabbitmqApi;

    @Autowired
    private AlipayPayCommons alipayPayCommons;

    /**
     * 异步通知
     */
    @SuppressWarnings("unchecked")
    @Override
    public String payAsyNotify(WeixinPayDTO wxDTO) {
        Map<String, String> params = null;
        //将实体类转化成map
        try {
            params = Common.convertBean(wxDTO);
            params.remove("way");
        } catch (Exception e) {
            logger.info("-----接收微信实体转化Map异常------" + e);
        }
        params = AlipayCore.paraFilter(params);  //将空字符串去除
        logger.info("----------微信异步请求参数---------" + params.toString());

        WxPayData data = new WxPayData();
        data.putAll(params);
        String sign = params.get("sign").toString(),
                str = data.makeSign();
        logger.info("----------验签sign-----------" + str);
        if (sign.equals(str)) {
            BasePayDTO basePayDTO = new BasePayDTO();
            basePayDTO.setOut_trade_no(wxDTO.getOut_trade_no());
            basePayDTO.setWay(wxDTO.getWay());
            basePayDTO.setUserId(wxDTO.getUserId());
            basePayDTO.setSign(wxDTO.getSign());
            basePayDTO.setType(wxDTO.getType());
            basePayDTO.setId(wxDTO.getId());
            PayBackDTO payBackDTO = new PayBackDTO();
            payBackDTO.setParams(params);
            payBackDTO.setBasePayDTO(basePayDTO);
            String ok = DozerUtils.map(rabbitmqApi.paymentProcessing(payBackDTO).getResult(),String.class);
            if(ok.equals(CommonConstants.SUCCESS)){
                return WxService.responseWx(true);
            }
        }
        logger.debug("微信支付通知");
        logger.debug("返回数据：");
        logger.debug("本地签名：" + str);
        return WxService.responseWx(false);
    }

    /**
     * 公共预付订单---目前支持两种类型 1: APP支付  2：扫码支付
     *
     * @param commonPayDTO
     * @return
     */
    public Map<String, Object> prepayOrder(CommonPayDTO commonPayDTO) {
        PayInfoDto payInfoDO = payInfoService.queryPayInfoByOrderId(commonPayDTO.getSerialNumber());
        Ensure.that(payInfoDO.getStatus().equals(CommonConstants.OrderPayStatus.YESPAY)).isFalse("09000008");  //订单状态不是未付款状态   //防止两个APP及以上同一账号在相同时间提交  交叉

        WxPayData data = new WxPayData();
        Date dt = new Date();
        data.put("time_start", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易起始时间
        if (CommonConstants.APP.equals(commonPayDTO.getTradeType())) {
            dt.setTime(dt.getTime() + (1800 * 1000));
        } else {
            dt.setTime(dt.getTime() + (3600 * 12 * 3 * 1000));
        }
        data.put("time_expire", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易结束时间
        //data.put("goods_tag", "lzhy20160505");//商品标记
        data.put("trade_type", commonPayDTO.getTradeType());                             //交易类型
        data.put("out_trade_no", String.valueOf(commonPayDTO.getSerialNumber()));       //本地订单号
        data.put("body", commonPayDTO.getSkuName());                   //商品名称
        data.put("total_fee", String.valueOf(commonPayDTO.getAmount().multiply(new BigDecimal("100")).intValue()));  //交易金额
        data.put("notify_url", Config.NOTIFY_URL);   //异步回调地址
        data.put("spbill_create_ip", Config.IP);     //用户发起请求IP地址
        data.put("appid", Config.APPID);
        data.put("mch_id", Config.MCHID);

        WxPayData result = WxPayApi.requestWXApi(data, Config.UNIFIEDORDER_URL, null),
                resultParams = new WxPayData();

        logger.info("微信支付发起");
        logger.info("请求数据：" + data.toJson());
        logger.info("返回数据：" + result.toJson());
        return WxService.getAppWxResponse(result, dt);
    }

    /**
     * 预付订单---APP支付
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> prepayOrder(MobileRequestDTO mqDTO) {
        PayInfoDto payInfoDO = payInfoService.queryPayInfoByOrderId(mqDTO.getOrderId());
        Ensure.that(payInfoDO.getStatus().equals(CommonConstants.OrderPayStatus.YESPAY)).isFalse("09000008");  //订单状态不是未付款状态   //防止两个APP及以上同一账号在相同时间提交  交叉

        WxPayData data = new WxPayData();
        Date dt = new Date();
        data.put("time_start", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易起始时间
        dt.setTime(dt.getTime() + (1800 * 1000));
        data.put("time_expire", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易结束时间
        //data.put("goods_tag", "lzhy20160505");//商品标记
        data.put("trade_type", CommonConstants.APP);                             //交易类型
        data.put("out_trade_no", String.valueOf(mqDTO.getOrderId()));       //本地订单号
        data.put("body", mqDTO.getPayOrderDTO().getSkuName());                   //商品名称
        data.put("total_fee", String.valueOf(mqDTO.getPayOrderDTO().getOrderAmount().multiply(new BigDecimal("100")).intValue()));  //交易金额
        data.put("notify_url", Config.NOTIFY_URL);   //异步回调地址
        data.put("spbill_create_ip", Config.IP);     //用户发起请求IP地址
        data.put("appid", Config.APPID);
        data.put("mch_id", Config.MCHID);

        WxPayData result = WxPayApi.requestWXApi(data, Config.UNIFIEDORDER_URL, null),
                resultParams = new WxPayData();

        logger.info("微信支付发起");
        logger.info("请求数据：" + data.toJson());
        logger.info("返回数据：" + result.toJson());
        return WxService.getAppWxResponse(result, dt);
    }

    /**
     * 请求微信退款接口(当一个订单号退款次数大于5次就会返回请求频繁)
     *
     * @param mqDTO
     * @return
     */
    public Map<String, Object> applyWXPayRefund(MobileRequestDTO mqDTO) {
        WxPayData data = WxPayApi.getWxPayData(mqDTO.getTargetType());
        data.put("out_trade_no", String.valueOf(mqDTO.getOrderId()));   //商户订单号
        data.put("out_refund_no", String.valueOf(mqDTO.getRefundNumber()));  //商户退款单号
        data.put("total_fee", Common.formatString(mqDTO.getAmount()));  //订单总额
        data.put("refund_fee", Common.formatString(mqDTO.getRefundAmount()));  //退款金额
        System.out.println(data.toJson());
        WxPayData result = WxPayApi.requestWXApi(data, Config.REFUND_URL, mqDTO.getTargetType()),
                resultParams = new WxPayData();
        logger.info("微信支付发起");
        logger.info("请求数据：" + data.toJson());
        logger.info("返回数据：" + result.toJson());

        PayRefundInfoDto priDO = new PayRefundInfoDto();
        priDO.setId(Long.valueOf(mqDTO.getId()));
        priDO.setSerialNumber(mqDTO.getOrderId());                               //退款订单号

        //当return_code和result_code都为success才算退款申请成功    --退款是否成功需定时任务
        if (result.get(CommonConstants.RETURN_CODE).equals(CommonConstants.SUCCESS) && result.get(CommonConstants.RESULT_CODE).equals(CommonConstants.SUCCESS)) {
            if (result.get("refund_id") != null)
                priDO.setThirdNumber(String.valueOf(result.get("refund_id")));  //微信退款订单号
            priDO.setStatus(CommonConstants.PayRefundStatus.DISPOSE.getIndex());
            resultParams.put("status", CommonConstants.PayRefundStatus.DISPOSE.getIndex());//退款中
            logger.info("APP返回数据：" + resultParams.toJson());
        } else {
            /*PayOrderParamsDTO paramsDTO = new PayOrderParamsDTO();
            paramsDTO.setOrderId(Long.valueOf(mqDTO.getSerialNumber()));
            paramsDTO.setStutas(2);
            paramsDTO.setAccount(BigDecimal.valueOf(Double.parseDouble(mqDTO.getRefundAmount())));
            boolean count = payOrderApi.updatePayByRefund(paramsDTO);
            Ensure.that(count).isFalse("09000071");*/

            priDO.setStatus(CommonConstants.PayRefundStatus.UNUSUAL.getIndex());
            resultParams.put("status", 2);   //退款异常
            logger.info("微信退款异常" + result.get(CommonConstants.RETURN_MSG));
        }

        //更新退款表
        int count = payRefundInfoService.updatePayRefundInfo(priDO);
        Ensure.that(count > 0).isTrue("09000070");
        logger.info("---订单退款结束---");
        return resultParams.toMap();
    }

    /**
     * 请求微信退款查询接口
     *
     * @param payRefundInfo
     * @return
     * @throws Exception
     */
    public void applyWXPayRefundQuery(PayRefundInfo payRefundInfo) throws Exception {
        logger.info("-----退款查询开始-------订单号:" + payRefundInfo.getOrderId());
        WxPayData data = new WxPayData();
        if (CommonConstants.PayTargetType.APP.getIndex() == payRefundInfo.getTargetType()) {
            data.put("appid", Config.APPID);
            data.put("mch_id", Config.MCHID);
        } else {
            data.put("appid", Config.WEB_APPID);
            data.put("mch_id", Config.WEB_MCHID);
        }

        data.put("out_trade_no", String.valueOf(payRefundInfo.getOrderId()));   //本地订单号
        WxPayData result = WxPayApi.requestWXApi(data, Config.REFUND_QUERY_URL, null),
                resultParams = new WxPayData();
        logger.info("微信支付发起");
        logger.info("请求数据：" + data.toJson());
        logger.info("返回数据：" + result.toJson());

        //当return_code和result_code都为success并且refund_status_$n未退款成功才算退款成功
        if (result.get(CommonConstants.RETURN_CODE).equals(CommonConstants.SUCCESS) && result.get(CommonConstants.RESULT_CODE).equals(CommonConstants.SUCCESS)) {
            PayRefundInfoDto priDO = new PayRefundInfoDto();
            priDO.setId(payRefundInfo.getId());
            //退款成功
            if (result.get(CommonConstants.REFUND_STATUS).equals(CommonConstants.SUCCESS)) {
                //更新订单状态退款修改 --后期优化成公共类
                alipayPayCommons.executeRefund(payRefundInfo.getOrderId(), 1);
                logger.error("--------订单状态处理完毕----------");
                //新增支付账单表   payBill
                PayBillDto pbDO = PayBillDto.convert(payRefundInfo);
                payBillService.createPayBill(pbDO);

                //退款表
                priDO.setStatus(CommonConstants.PayRefundStatus.SUCCESS.getIndex());  //退款成功
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                priDO.setUpdateTime(DateUtil.format(new Date()));  //更新时间
                priDO.setSuccessTime(String.valueOf(result.get("refund_success_time_0")));  //退款支付时间

                //退款处理中  //不做任何处理---当前数据库状态是退款中
            } else if (result.get(CommonConstants.REFUND_STATUS).equals("PROCESSING")) {
                //退款异常   -- 商家人工自己处理
            } else if (result.get(CommonConstants.REFUND_STATUS).equals("CHANGE")) {
                priDO.setStatus(CommonConstants.PayRefundStatus.UNUSUAL.getIndex());
                //未确定     需要商户后台人工用原退款单号重新发起退款申请--
            } else if (result.get(CommonConstants.REFUND_STATUS).equals("NOTSURE")) {
                priDO.setStatus(CommonConstants.PayRefundStatus.INDETERM.getIndex());
                //已关闭   后台人工处理 1.退款成功后自行关闭   2.退款失败后自行关闭
            } else if (result.get(CommonConstants.REFUND_STATUS).equals("REFUNDCLOSE")) {
                priDO.setStatus(CommonConstants.PayRefundStatus.CLOSE.getIndex());
            }
            payRefundInfoService.updatePayRefundInfo(priDO);
            logger.info("---查询订单退款结束---订单号:" + payRefundInfo.getOrderId());
        } else {
            resultParams.put("status", CommonConstants.PayRefundStatus.UNUSUAL);   //退款异常
            logger.info("微信退款查询异常" + result.get(CommonConstants.RETURN_MSG));
        }
    }

//    /**
//     * 预付订单---Web支付
//     */
//    public Map<String, Object> webPrepayOrder(WebPayDTO webPayDTO) {
//        //根据code获取openid
//        JSONObject json = WxService.getWebOpenid(webPayDTO.getCode());
//        //生成预付订单
//        WxPayData data = new WxPayData();
//        if (json == null) {
//            logger.error("----- WxService.getWebOpenid(webPayDTO.getCode())----- === " + json);
//        } else {
//            data.put("openid", json.get("openid") + "");
//            logger.info("-----openid-----" + json.get("openid"));
//        }
//        Date dt = new Date();
//        data.put("time_start", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易起始时间
//        dt.setTime(dt.getTime() + (1800 * 1000));
//        data.put("time_expire", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易结束时间
//        data.put("trade_type", CommonConstants.WEB);                             //交易类型
//        data.put("out_trade_no", String.valueOf(webPayDTO.getPayOrderDTO().getOrderId()));       //本地订单号
//        data.put("body", webPayDTO.getPayOrderDTO().getSkuName());                   //商品名称
//        if (com.lzy.framework.core.utils.StringUtil.trimToNull(webPayDTO.getSkuName()) != null)
//            data.put("body", webPayDTO.getSkuName());                   //商品名称
//        data.put("total_fee", String.valueOf(webPayDTO.getPayOrderDTO().getOrderAmount().multiply(new BigDecimal("100")).intValue()));  //交易金额
//        data.put("notify_url", Config.NOTIFY_URL);   //异步回调地址
//        data.put("spbill_create_ip", Config.IP);     //用户发起请求IP地址
//        data.put("appid", Config.WEB_APPID);
//        data.put("mch_id", Config.WEB_MCHID);
//
//        WxPayData result = WxPayApi.requestWXApi(data, Config.UNIFIEDORDER_URL, null);
//        logger.info("微信支付发起");
//        logger.info("请求数据：" + data.toJson());
//        if (result == null)
//            logger.info("返回数据：" + result.toJson());
//        else
//            logger.info("返回数据：" + result.toJson());
//        return WxService.getWebWxResponse(result, dt);
//    }
//
//    /**
//     * 小程序预付订单
//     *
//     * @param smallAppletPayDTO
//     * @return
//     */
//    public Map<String, Object> smallAppletPrepayOrder(SmallAppletPayDTO smallAppletPayDTO) {
//        AppletKDCDto appletKDCDto = appletKDCServiceApi.findAppletKDCByShopId(smallAppletPayDTO.getShopId());
//        Ensure.that(appletKDCDto).isNotNull("09000105");
//        //根据code获取openid
//        JSONObject json = WxService.getAppOpenid(smallAppletPayDTO.getCode(), appletKDCDto);
//        logger.info("-----openid-----" + json);
//        //生成预付订单
//        WxPayData data = new WxPayData();
//        Date dt = new Date();
//        data.put("time_start", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易起始时间
//        dt.setTime(dt.getTime() + (1800 * 1000));
//        data.put("time_expire", StringUtil.dateFormat(dt, "yyyyMMddHHmmss"));//交易结束时间
//        data.put("trade_type", CommonConstants.WEB);                             //交易类型
//        data.put("out_trade_no", String.valueOf(smallAppletPayDTO.getPayOrderDTO().getOrderId()));       //本地订单号
//        data.put("body", smallAppletPayDTO.getPayOrderDTO().getSkuName());                   //商品名称
//        data.put("total_fee", String.valueOf(smallAppletPayDTO.getPayOrderDTO().getOrderAmount().multiply(new BigDecimal("100")).intValue()));  //交易金额
//        data.put("notify_url", Config.NOTIFY_URL);   //异步回调地址
//        data.put("spbill_create_ip", Config.IP);     //用户发起请求IP地址
//        data.put("appid", appletKDCDto.getAppId());
//        data.put("mch_id", Config.MCHID);
//        data.put("openid", json.get("openid") + "");
//
//        WxPayData result = WxPayApi.requestWXApi(data, Config.UNIFIEDORDER_URL, null),
//                resultParams = new WxPayData();
//
//        logger.info("微信支付发起");
//        logger.info("请求数据：" + data.toJson());
//        logger.info("返回数据：" + result.toJson());
//        return WxService.getWebWxResponse(result, dt);,
//    }
}
